package cn.edu.dutir.utility;

import java.util.HashMap;
import java.util.Map;

/**
 * An <code>ObjectToSet</code> provides a {@link java.util.Map} from
 * arbitrary objects to objects of class {@link java.util.Map}.
 *
 */
public class ObjectToMap<K1, K2> extends HashMap<K1, Map<K2, Integer>> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6808746610438019558L;

    /**
     * Add a member(here, a member is <subKey,value> pair) to the value 
     * of the map mapped to by the specified key.
     *<p><b>Note</b>:This procedure accumulates result if specified map item
     * already exist.
     * @param key Key whose map value will have the <subKey,value> pair.
     * @param subKey Key whose map value will have the object.
     * @param value The value to be accumulated to the value of the 
     * corresponding subKey.
     */
	public void addMember(K1 key, K2 subKey, Integer value) {
		Map<K2, Integer> subMap = get(key);
		if (subMap != null) {
			Integer oldValue = subMap.get(subKey);
			if (oldValue != null) {
				subMap.put(subKey, oldValue + value);
			} else {
				subMap.put(subKey, value);
			}
		} else {
			Map<K2, Integer> map = new HashMap<K2, Integer>();
			map.put(subKey, value);
			put(key, map);
		}
	}

	/**
	 * Get the 
	 * @param key
	 * @param subKey
	 * @return
	 */
	public Integer getMember(K1 key, K2 subKey) {
		Map<K2, Integer> subMap = get(key);
		if (subMap != null) {
			Integer value = subMap.get(subKey);
			return value != null ? value : new Integer(0);
		} else {
			return new Integer(0);
		}
	}

	/**
	 * Removes the specified value from the set of values assigned to the
	 * specified key.
	 * 
	 * @param key Key whose members will be removed if contains.
     * @return <code>true</code> if the value was in the set of
     * members for the key.
	 */
	public boolean removeMember(K1 key) {
		return remove(key) != null;
	}

	/**
	 * Removes the specified value,corresponding to subKey, the  from the secondary 
	 * map which can be located by key.
	 * 
	 * @param key Key used to locate the secondary map where the value really lies in.
	 * @param subKey. Key whose members will be removed if contains.
     * @return <code>true</code> if the value was in the set of
     * members for the key.
	 */
	public boolean removeMember(K1 key, K2 subKey) {
		Map<K2, Integer> element = get(key);
		if (element != null) {
			return element.remove(subKey) != null;
		}
		return false;
	}
}
